home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-07-11 | 17.5 KB | 536 lines | [TEXT/PJMM] |
- unit UserLog;
-
- { Unit to backup, sort and zero user minutes in a Red Ryder Host UserLog }
- { and to reset CallerLog and TabbyLog. }
-
- { Written by Pete Johnson for the Glassell Park BBS 213-254-4133 }
-
- { Date of last revision: April 14, 1991 }
-
-
- interface
-
- uses
- Globals, HelloTabby, mehitFile, LogUtils;
-
- type
-
- OldNum = longint;
- MNA = record
- HowMany: longint;
- OldNumbers: array[1..1] of OldNum;
- end;
- MNAPtr = ^MNA;
- MNAHdl = ^MNAPtr;
-
- var
- myMNAHdl: MNAHdl;
- ULRecSize: longint;
-
-
- procedure ProcessUserLog;
-
- implementation
-
- type
- WhenCalled = packed array[1..6] of char;
- UserRecord = packed record
- FirstName: string[15];
- LastName: string[15];
- CallingFromAndPW: packed array[1..40] of char;
- NumberOfCalls: integer;
- DateLastCalled: WhenCalled;
- TCMRRF: packed array[1..6] of char; {Time, Clearance, Minutes last call, Reserved, Reserved, Flags}
- Uploads: integer;
- Downloads: integer;
- PrivMsg: integer;
- PubMsg: integer;
- MRRF: packed array[1..6] of char;
- HiMsgRead: longint;
- CombinedReads: packed array[1..32] of char
- end;
-
- const
- DELETED = 64;
-
- {----------------------------------------------------------------- }
-
- function StripTime (inString: str255): str255;
-
- { turns standard DateString of 04/01/91 1:00:06 into 04/01/91 }
-
- begin
- StripTime := copy(inString, 1, pos(' ', inString) - 1);
- end;
-
- {----------------------------------------------------------------- }
-
- var
- ThisUser: UserRecord;
- DialogPointer: DialogPtr;
- fndrInfo: FInfo;
- NewRefNum, ULRefNum, Count, StuffRef: integer;
- logicalEOF, HowManyUsers: longint;
- Today: DateTimeRec;
- ResourceHandle: StringHandle;
- StuffResource: Handle;
- NowSecs: longint;
-
- {----------------------------------------------------------------- }
-
- procedure NoMem;
-
- var
- MemDialog: DialogPtr;
- MemItem: integer;
-
- begin
- MemDialog := GetNewDialog(1003, nil, Pointer(-1));
- SetPort(MemDialog);
- FrameDItem(MemDialog, Ok);
- DrawDialog(MemDialog);
- ModalDialog(nil, MemItem);
- repeat
- until MemItem = 1;
- DisposDialog(MemDialog);
- ExitToShell;
- end;
-
- {------------------------------}
-
- function BigString (Number: integer): string;
-
- { Function changes two-digit number to a two-character string. }
-
- begin
- BigString := concat(Int2Char(Number div 10), Int2Char(Number mod 10))
- end;
-
- { ------------------------------------------------------ }
-
- procedure SortUserLog;
-
- type
- UserPointer = ^UserRecord;
- UserHandle = ^UserPointer;
- UserArray = array[1..1] of UserHandle;
- UArrayPtr = ^UserArray;
- UArrayHdl = ^UArrayPtr;
- SortRecord = record
- IndexNo: integer;
- IndexString: packed array[1..7] of char;
- end;
- SortArray = array[1..1] of SortRecord;
- SortArrayPtr = ^SortArray;
- SortArrayHdl = ^SortArrayPtr;
-
- var
- UserLogHdl: UArrayHdl;
- myArrayHdl: SortArrayHdl;
- UserCount1, UserCount2, SortedUser, ULRef: integer;
- HeadCount: longint;
-
- procedure QuickSort (Start, Finish: integer; var TheArray: SortArrayHdl);
-
- { Sorts array Users by Clearance+Date field using QuickSort }
-
- var
- Left, Right: integer;
- StarterValue: packed array[1..7] of char;
- Temp: SortRecord;
-
- begin
- Left := Start;
- Right := Finish;
- StarterValue := TheArray^^[(Start + Finish) div 2].IndexString; { Pick a starter }
- repeat
- while TheArray^^[Left].IndexString < StarterValue do
- Left := Left + 1; { Find a bigger value on the left }
- while StarterValue < TheArray^^[Right].IndexString do
- Right := Right - 1; { Find a smaller value on the right }
- if Left <= Right then
- begin {If we haven't gone too far... }
- Temp := TheArray^^[Left];
- TheArray^^[Left] := TheArray^^[Right];
- TheArray^^[Right] := Temp;
- Left := Left + 1;
- Right := Right - 1
- end; { then }
- until Right <= Left;
- if Start < Right then
- QuickSort(Start, Right, TheArray);
- if Left < Finish then
- QuickSort(Left, Finish, TheArray)
- end; { procedure QuickSort }
-
- begin
- ULRecSize := SizeOf(UserRecord);
- Err := FSOpen(ULPath, vRefNum, ULRef);
- Err := SetFPos(ULRef, fsFromStart, ULRecSize); { Sysop is at seek position zero, so we skip it }
- Err := GetEOF(ULRef, logicalEOF);
- HeadCount := logicalEOF div ULRecSize;
- UserCount1 := 1;
- myArrayHdl := nil;
- UserLogHdl := nil;
- myArrayHdl := SortArrayHdl(NewHandle(SizeOf(SortArray) + ((HeadCount - 1) * SizeOf(SortRecord))));
- if myArrayHdl <> nil then
- UserLogHdl := UArrayHdl(NewHandle(SizeOf(UserArray) + ((HeadCount - 1) * SizeOf(UserRecord))));
- if (myArrayHdl <> nil) & (UserLogHdl <> nil) then
- begin
- MoveHHi(Handle(myArrayHdl));
- HLock(Handle(myArrayHdl));
- MoveHHi(Handle(UserLogHdl));
- HLock(Handle(UserLogHdl));
- if (HeadCount > 2) then
- begin
- for UserCount1 := 2 to HeadCount do { skip 1 to allow for missing sysop }
- begin
- UserLogHdl^^[UserCount1] := UserHandle(NewHandle(ULRecSize));
- Err := FSRead(ULRef, ULRecSize, Ptr(UserLogHdl^^[UserCount1]^));
- myArrayHdl^^[UserCount1].IndexNo := UserCount1;
- myArrayHdl^^[UserCount1].IndexString := concat(UserLogHdl^^[UserCount1]^^.TCMRRF[2], UserLogHdl^^[UserCount1]^^.DateLastCalled);
- end; { for UserCount1 := 1 to HeadCount - 1 }
-
- QuickSort(2, HeadCount, myArrayHdl);
-
- Err := SetFPos(ULRef, fsFromStart, ULRecSize); { Sysop is at seek position zero, so we skip it }
-
- for UserCount2 := HeadCount downto 2 do { Write in reverse to get proper order }
- begin
- SortedUser := myArrayHdl^^[UserCount2].IndexNo;
- Err := FSWrite(ULRef, ULRecSize, @UserLogHdl^^[SortedUser]^^);
- DisposHandle(Handle(UserLogHdl^^[SortedUser]));
- end; { for UserCount2 := UserCount1 downto 1 }
-
- if myArrayHdl <> nil then
- begin
- HUnlock(Handle(myArrayHdl));
- DisposHandle(Handle(myArrayHdl));
- myArrayHdl := nil;
- end;
- if UserLogHdl <> nil then
- begin
- HUnlock(Handle(UserLogHdl));
- DisposHandle(Handle(UserLogHdl));
- UserLogHdl := nil;
- end;
- end { if (myArrayHdl <> nil) & (UserLogHdl <> nil) }
- else
- NoMem;
- Err := FSClose(ULRef)
- end { (HeadCount > 2) }
- end;
-
- { ------------------------------------------------------ }
-
- function UserHasExpired (DateOfLastCall: WhenCalled; DaysAllowed: longint): boolean;
-
- var
- UserDTR: DateTimeRec;
- UserSecs: longint;
-
- begin
- UserDTR.Year := BitAnd(ord(DateOfLastCall[1]), 255) + 1900;
- UserDTR.Month := BitAnd(ord(DateOfLastCall[2]), 255);
- UserDTR.Day := BitAnd(ord(DateOfLastCall[3]), 255);
- UserDTR.Hour := 0;
- UserDTR.Minute := 0;
- UserDTR.Second := 0;
- Date2Secs(UserDTR, UserSecs);
- if (NowSecs - UserSecs) > (DAYSECS * DaysAllowed) then
- UserHasExpired := true
- else
- UserHasExpired := false
- end;
-
- { ------------------------------------------------------ }
-
- procedure GetFromAndPW (var From, PW: str255);
-
- var
- Counter: integer;
-
- begin
- From := '';
- for Counter := 2 to ord(ThisUser.CallingFromAndPW[1]) + 1 do
- From := concat(From, ThisUser.CallingFromAndPW[Counter]);
- PW := '';
- for Counter := 33 to ord(ThisUser.CallingFromAndPW[32]) + 32 do
- PW := concat(PW, ThisUser.CallingFromAndPW[Counter]);
- end;
-
- { ------------------------------------------------------ }
-
- procedure WriteDeleteLog (ReasonDeleted: str255);
-
- var
- DeleteRef, Counter: integer;
- ULDeleteFile, Password, FromString, LogString: str255;
-
- begin
- if MultiFinder then
- IgnoreBool := WaitNextEvent(EveryEvent, TabbyEventRec, sleep, nil);
- ULDeleteFile := concat(DefaultsPtr^.DBackupPath, 'Users Deleted');
- Err := FSOpen(ULDeleteFile, vRefNum, DeleteRef);
- if Err <> NoErr then
- begin
- Err := Create(ULDeleteFile, vRefNum, DefaultsPtr^.TEXTType, 'TEXT');
- Err := FSOpen(ULDeleteFile, vRefNum, DeleteRef);
- Err := WrLn(DeleteRef, ' Calls Last UL DL Pub Pri Lev Min Reason');
- end;
- if Err = NoErr then
- begin
- Err := SetFPos(DeleteRef, FSFromLEOF, 0);
- GetFromAndPW(FromString, Password);
- with ThisUser do
- begin
- LogString := concat(FirstName, ' ', LastName, ' from ', FromString);
- LogString := concat(LogString, ' [', Password, ']', ENDLINE);
- LogString := concat(LogString, StripTime(DateString), ' ', StringOf(NumberOfCalls : 4), ' ');
- LogString := concat(LogString, BigString(ord(DateLastCalled[2])), '/');
- LogString := concat(LogString, BigString(ord(DateLastCalled[3])), '/');
- LogString := concat(LogString, BigString(ord(DateLastCalled[1])), ' ');
- LogString := concat(LogString, StringOf(Uploads : 4), ' ');
- LogString := concat(LogString, StringOf(Downloads : 4), ' ');
- LogString := concat(LogString, StringOf(PubMsg : 4), ' ');
- LogString := concat(LogString, StringOf(PrivMsg : 4), ' ');
- LogString := concat(LogString, StringOf(ord(TCMRRF[2]) : 3), ' ');
- LogString := concat(LogString, StringOf(ord(TCMRRF[1]) : 3), ' ', ReasonDeleted)
- end; {with ThisUser}
- Err := WrLn(DeleteRef, LogString)
- end;
- Err := FSClose(DeleteRef)
- end;
-
- { ------------------------------------------------------ }
-
- procedure BackUserLog;
-
- const
- MaxBadNames = 100;
-
- var
- FilePointer: Ptr;
- ULCounter: longint;
- BadNameFile, HowManyBadNames, Counter, i, ULCopyRefNum: integer;
- NewULog, TheBAK: str255;
- BadNames: array[1..MaxBadNames] of string[15];
- GoodUser, isDeleted: boolean;
- ReasonDeleted, SitName: str255;
- HowManyCharacters, tempDirRef, tempVRef, tempLong, MsgNumAdjust, NewFileLength: longint;
-
- begin
- if MultiFinder then
- IgnoreBool := WaitNextEvent(EveryEvent, TabbyEventRec, sleep, nil);
- ULRecSize := SizeOf(UserRecord);
- GetDateTime(NowSecs);
- for Counter := 1 to MaxBadNames do
- BadNames[Counter] := '';
- Err := FSOpen(concat(gDefaultpath, 'Bad User Names'), vRefNum, BadNameFile);
- Counter := 1;
- while (Err = NoErr) & (Counter < MaxBadNames + 1) do
- begin
- Err := ReadALine(BadNameFile, BadNames[Counter]);
- if BadNames[Counter] = '' then
- leave;
- Counter := succ(Counter);
- end;
- HowManyBadNames := Counter - 1;
- Err := FSClose(BadNameFile);
- if MultiFinder then
- IgnoreBool := WaitNextEvent(EveryEvent, TabbyEventRec, sleep, nil);
- NewULog := concat(ULPath, '.$$$');
- TheBAK := concat(ULPath, '.BAK');
- while FileExists(NewULog) do
- Err := FSDelete(NewULog, vRefNum);
- Err := Create(NewULog, vRefNum, 'ULED', 'ULOG');
- Err := FSOpen(NewULog, vRefNum, NewRefNum);
- Err := SetFPos(NewRefNum, fsFromStart, 0);
- Err := FSOpen(ULPath, vRefNum, ULRefNum);
- Err := GetEOF(ULRefNum, logicalEOF);
- Err := SetFPos(ULRefNum, fsFromStart, 0);
- HowManyUsers := logicalEOF div ULRecSize;
- for ULCounter := 1 to HowManyUsers do
- with DefaultsPtr^ do
- begin
- if MultiFinder then
- IgnoreBool := WaitNextEvent(EveryEvent, TabbyEventRec, sleep, nil);
- Err := FSRead(ULRefNum, ULRecSize, @ThisUser);
- ReasonDeleted := 'Unknown';
- isDeleted := BitAnd(ord(ThisUser.TCMRRF[6]), DELETED) = DELETED;
- if DoChangeLevel then
- if (ThisUser.TCMRRF[2] = chr(ChangeLevel)) then
- begin
- GoodUser := true;
- for Counter := 1 to HowManyBadNames do
- if (EqualString(ThisUser.FirstName, BadNames[Counter], false, false)) | (EqualString(ThisUser.LastName, BadNames[Counter], false, false)) then
- begin
- GoodUser := false;
- ThisUser.TCMRRF[1] := chr(0); { zero time }
- ThisUser.TCMRRF[2] := chr(0); { zero access }
- ThisUser.TCMRRF[6] := chr(DELETED); { delete }
- ReasonDeleted := 'Bad Name';
- isDeleted := true;
- leave
- end;
- if GoodUser then
- begin
- ThisUser.TCMRRF[1] := chr(ChangeToMin);
- ThisUser.TCMRRF[2] := chr(ChangeToLevel);
- end
- end; { if (ThisUser.TCMRRF[2] = chr(Newcomer)) }
- if DefaultsPtr^.ZeroMin then
- ThisUser.TCMRRF[3] := chr(0);
- if (ord(ThisUser.TCMRRF[2]) <= CheckLevel) & (ULCounter <> 1) then
- begin
- if KillOld then
- if UserHasExpired(ThisUser.DateLastCalled, InactiveDays) then
- begin
- ThisUser.TCMRRF[6] := chr(DELETED);
- isDeleted := true;
- ReasonDeleted := 'Inactive'
- end;
- if KillOldOneCalls then
- if (ThisUser.NumberOfCalls < 2) then
- if UserHasExpired(ThisUser.DateLastCalled, OneCallDays) then
- if ((ThisUser.Uploads + ThisUser.Downloads + ThisUser.PrivMsg + ThisUser.PubMsg) < 1) then
- begin
- ThisUser.TCMRRF[6] := chr(DELETED);
- isDeleted := true;
- ReasonDeleted := 'One-Timer'
- end;
- end; { if (ord(ThisUser.TCMRRF[2]) <= CheckLevLong) & (ULCounter <> 1) }
- if MultiFinder then
- IgnoreBool := WaitNextEvent(EveryEvent, TabbyEventRec, sleep, nil);
- if UseVetFlag & (ThisUser.NumberOfCalls > VetCalls) then
- begin
- tempLong := ord(ThisUser.MRRF[6 - ((VetFlag - 1) div 8)]);
- if SetVetFlag then
- BSET(tempLong, (VetFlag - 1) mod 8)
- else
- BCLR(tempLong, (VetFlag - 1) mod 8);
- ThisUser.MRRF[6 - ((VetFlag - 1) div 8)] := chr(tempLong mod 256);
- end; {if UseVetFlag & (ThisUser.NumberOfCalls > VetCalls)}
- if (ThisUser.TCMRRF[2] = chr(DeleteLevel)) & DeleteByLevel & (ReasonDeleted <> 'Bad Name') then
- ReasonDeleted := 'Bad Level';
- { Next section checks TCMRFF byte 2 to see if clearance is valid }
- if (ThisUser.TCMRRF[2] <> chr(DeleteLevel)) | (not DeleteByLevel) then
- begin
- if (not isDeleted) | (not SkipDeletes) then
- begin
- if (DefaultsPtr^.Renumber) & (ThisUser.HiMsgRead > 1) then
- begin
- MoveHHi(Handle(myMNAHdl));
- HLock(Handle(myMNAHdl));
- for MsgNumAdjust := 1 to myMNAHdl^^.HowMany do
- begin
- if (ThisUser.HiMsgRead < myMNAHdl^^.OldNumbers[MsgNumAdjust]) then
- begin
- ThisUser.HiMsgRead := pred(MsgNumAdjust);
- leave
- end
- else if ThisUser.HiMsgRead = myMNAHdl^^.OldNumbers[MsgNumAdjust] then
- begin
- ThisUser.HiMsgRead := MsgNumAdjust;
- leave
- end;
- end; { for MsgNumAdjust := 1 to myMNAHdl^^.HowMany }
- if ThisUser.HiMsgRead < 0 then
- ThisUser.HiMsgRead := 0
- else if ThisUser.HiMsgRead > myMNAHdl^^.HowMany then
- ThisUser.HiMsgRead := myMNAHdl^^.HowMany;
- end; { if (DefaultsPtr^.Renumber) & (ThisUser.HiMsgRead > 1) }
- HUnlock(Handle(myMNAHdl));
- Err := FSWrite(NewRefNum, ULRecSize, @ThisUser);
- end; {if (not isDeleted) | (not SkipDeletes)}
- end; {if (ThisUser.TCMRRF[2] <> chr(DeleteLevel)) | (not DeleteByLevel)}
- if isDeleted & SkipDeletes & LogDeletes then
- WriteDeleteLog(ReasonDeleted);
- end; {for ULCounter := 1 to HowManyUsers do }
- Err := GetFPos(NewRefNum, NewFileLength);
- Err := SetEOF(NewRefNum, NewFileLength);
- Err := FSClose(ULRefNum);
- Err := FSClose(NewRefNum);
- while FileExists(TheBAK) do
- Err := FSDelete(TheBAK, vRefNum); { Delete old Userlog.BAK }
- Err := Rename(ULPath, vRefNum, TheBAK); { Rename Userlog to Userlog.BAK }
- while FileExists(ULPath) do
- Err := FSDelete(ULPath, vRefNum); { Delete old Userlog }
- Err := Rename(NewULog, vRefNum, ULPath); { Rename Userlog.$$$ to Userlog }
-
- if myMNAHdl <> nil then
- begin
- DisposHandle(Handle(myMNAHdl));
- myMNAHdl := nil
- end;
-
- if DefaultsPtr^.DBackupMode in [StuffNone..StuffBestGuess] then
- while FileExists(TheBAK) do
- Err := FSDelete(TheBAK, vRefNum) { Delete Userlog.BAK -- it's stuffed }
- else
- begin {need to restore UserLog to original file so aliases in System 7 work }
- Err := CopyFile(TheBAK, NewULog); { copy UL.BAK into UL.$$$ }
- while FileExists(TheBAK) do
- Err := FSDelete(TheBAK, vRefNum); { Delete old Userlog.BAK }
- Err := CopyFile(ULPath, TheBAK); { copy UL into UL.BAK }
- while FileExists(ULPath) do
- Err := FSDelete(ULPath, vRefNum); { delete UL }
- Err := Rename(TheBAK, vRefNum, ULPath); { rename UL.BAK to UL }
- Err := Rename(NewULog, vRefNum, TheBAK); { rename UL.$$$ to UL.BAK }
- end;
- if MultiFinder then
- IgnoreBool := WaitNextEvent(EveryEvent, TabbyEventRec, sleep, nil);
- end;
-
- { ------------------------------------------------------ }
-
- procedure ProcessUserLog;
-
- var
- TempString: str255;
-
- begin
- if DefaultsPtr^.ProcessUL then
- begin
- if MultiFinder then
- IgnoreBool := WaitNextEvent(EveryEvent, TabbyEventRec, sleep, nil);
- TextFont(0);
- TextSize(12);
- ForeColor(BlueColor);
- TempString := 'mehitabel: doing users…';
- EraseRect(StatusRect);
- TextBox(Pointer(ord(@TempString) + 1), length(TempString), StatusRect, teJustLeft);
- TempString := 'backing';
- EraseRect(MsgNoRect);
- TextFont(Geneva);
- TextSize(9);
- ForeColor(RedColor);
- TextBox(Pointer(ord(@TempString) + 1), length(TempString), MsgNoRect, teJustRight);
- TextFont(0);
- TextSize(12);
- ForeColor(BlueColor);
- BackUserLog;
- TempString := 'sorting';
- EraseRect(MsgNoRect);
- TextFont(Geneva);
- TextSize(9);
- ForeColor(RedColor);
- TextBox(Pointer(ord(@TempString) + 1), length(TempString), MsgNoRect, teJustRight);
- if DefaultsPtr^.SortUserLog then
- SortUserLog;
- if DefaultsPtr^.WriteToTabby then
- begin
- if MultiFinder then
- IgnoreBool := WaitNextEvent(EveryEvent, TabbyEventRec, sleep, nil);
- TimeStamp;
- Err := FSOpen(concat(gDefaultpath, 'Tabby:Tabby Log'), DefaultVol, TLogRef);
- Err := SetFPos(TLogRef, fsFromLEOF, 0);
- Err := WrLn(TLogRef, concat(DateString, ' mehitabel - ', stringOf(HowManyUsers : 1), ' users processed'));
- Err := FSClose(TLogRef)
- end
- end
- end;
-
- { ------------------------------------------------------ }
-
- end.